﻿module EvalTests

open NUnit.Framework
open FParsec
open JsParser
open JsAst
open JsTypes
open JsEval
open JsEngine


[<TestFixture>]
type testEval() =

    (* expects a valid parse and returns value *)
    member self.parse src : 'a =
        let result = parseJs src 
        match result with
        | Success(result,_,_) -> result

    member self.eval src = 
        let defaultEnv = createTopFrame [] Undefined
        let ast = self.parse src
        let (Value(x)) = evalStmts ast defaultEnv
        x
   
    [<Test>]
    member self.test1() =
        let value = self.eval """2+2"""
        Assert.AreEqual(Number(4.0), value)

    [<Test>]
    member self.test2() =
        let value = self.eval """2+2*7"""
        Assert.AreEqual(Number(16.0), value)

    [<Test>]
    member self.var() =
        let value = self.eval """var x = 2+2*7; x+2"""
        Assert.AreEqual(Number(18.0), value)

    [<Test>]
    member self.assign() =
        let value = self.eval """
        var a = 1;a=2;a
        """
        Assert.AreEqual(Number(2.0), value)

    [<Test>]
    member self.inc() =
        let value = self.eval """
        var a = 1, b=a++;
        a;
        """
        Assert.AreEqual(Number(2.0), value)

    [<Test>]
    member self.preInc() =
        let value = self.eval """
        var a = 1, b=++a;
        b;
        """
        Assert.AreEqual(Number(2.0), value)

    [<Test>]
    member self.functionExpressionReturn() =
        let value = self.eval """
        var f = function() { return 17; };
        f();
        """
        Assert.AreEqual(Number(17.0), value)

    [<Test>]
    member self.functionDecl() =
        let value = self.eval """
        function f() { return 17; };
        f();
        """
        Assert.AreEqual(Number(17.0), value)

[<TestFixture>]
type testEvalWithBuiltins() =

    [<Test>]
    member self.objProperty() =
        let engine = JsEngine([])
        let value = engine.eval """
        var o = new Object;
        o.a = 17:
        o.a;
        """
        Assert.AreEqual(Number(17.0), value)